package com.yunhe.authority.service.authority;

import com.yunhe.authority.domain.authority.Menu;
import com.yunhe.authority.domain.authority.ProejctRoleOrg;
import com.yunhe.common.model.PageParam;
import com.yunhe.authority.domain.authority.Role;
import com.yunhe.authority.domain.authority.User;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.DatabaseProcessException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 角色Service
 * @desc 角色服务类定义
 * @author liuronglei
 */
public interface RoleService {

    /**
     * 新增角色
     * @param parentId 父角色id
     * @param stationId 项目id
     * @param firmId    单位id
     * @param role      角色对象
     * @return
     * @throws ArgumentErrorException
     * @throws UniqueConstraintsException
     * @throws ObjectNotFoundException
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    Role createRole(Long parentId,Long stationId,Long firmId, Role role)
            throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException;

    /**
     * 根据id删除角色
     * @param roleId 角色ID
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void deleteRole(Long roleId) throws ArgumentErrorException;

    /**
     * 根据ids删除角色
     * @param ids 角色IDs
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void deleteRoleByIds(String ids) throws ArgumentErrorException;

    /**
     * 更新角色
     * @param role 要更新的角色对象
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    Role updateRole(Role role)
            throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException;

    /**
     * 更新角色
     * @param roleId 角色ID
     * @param name 角色编号
     * @param title 角色标题
     * @param activity 是否可用
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    Role updateRole(Long roleId,
                    String name,
                    String title,
                    String activity)
            throws ArgumentErrorException, ObjectNotFoundException, UniqueConstraintsException;

    /**
     * 根据ID获得角色对象
     * @param roleId 角色ID
     */
    Role findByRoleId(Long roleId);

    /**
     * 根据角色编号获得角色对象
     * @param name 角色编号
     */
    Role findByName(String name);

    /**
     * 根据条件获得所有用户对象
     * @param name 角色编号
     * @param title 角色标题
     * @param pageParam 分页对象
     */
    Iterable<Role> findRoles(Long userId, String name, String title, PageParam pageParam);

    Iterable<Role> findRoles(Long userId, String title, PageParam pageParam);

    Iterable<Role> getRoles(Long userId, String name, String title, PageParam pageParam);

    Iterable<Role> findRole(Long userId, String name, String title, PageParam pageParam);

    Iterable<Role> findRole(Long userId);

    Iterable<Role> findRoles(String name, String title, PageParam pageParam);

    Page<Role> findAllRoles(String keywords, PageParam pageParam);

    /**
     * 根据用户ID获得角色列表
     * @param userId 用户ID
     */
    Iterable<Role> findRolesByUserId(Long userId);

    /**
     * 根据角色ID获得菜单列表
     * @param roleId 角色ID
     */
    Iterable<Menu> findMenusByRoleId(Long roleId);

    Iterable<Menu> findHasMenusByRoleId(Long roleId);

    Iterable<Menu> findAppMenusByRoleId(Long roleId);

    Iterable<Menu> findHasAppMenusByRoleId(Long roleId);

    /**
     * 根据角色ID获得用户列表
     * @param roleId 角色ID
     * @param userId
     */
    Iterable<User> findUsersByRoleId(Long roleId, Long userId);

    /**
     * 角色绑定菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void bindMenu(Long roleId, Long menuId)
            throws DatabaseProcessException;

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void bindHasMenu(Long roleId, Long menuId)
            throws DatabaseProcessException;

    /**
     * 角色绑定APP菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void bindAppMenu(Long roleId, Long menuId)
            throws DatabaseProcessException;

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void bindHasAppMenu(Long roleId, Long menuId)
            throws DatabaseProcessException;

    /**
     * 解绑菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void unbindMenu(Long roleId, Long menuId);

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void unbindAppMenu(Long roleId, Long menuId);

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void unbindHasMenu(Long roleId, Long menuId);

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void unbindHasAppMenu(Long roleId, Long menuId);

    /**
     * 批量更新菜单绑定
     * @param roleId 角色ID
     * @param menuIdList 菜单ID列表
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void updateMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException;

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void updateAppMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException;

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void updateHasMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException;

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void updateHasAppMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException;

    Iterable<User> findUsersById(Long id);

    Page<User> findUsersByIdAndCondition(Long id, String keywords, PageParam pageParam);

    /**
     * 角色绑定电站
     * @param roleId 角色ID
     * @param stationId 菜单ID
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void bindStation(Long roleId, Long stationId)
            throws DatabaseProcessException;

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void bindHasStation(Long roleId, Long stationId)
            throws DatabaseProcessException;

    /**
     * 解绑电站
     * @param roleId 角色ID
     * @param stationId 菜单ID
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void unbindStation(Long roleId, Long stationId);

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void unbindHasStation(Long roleId, Long stationId);

    /**
     * 批量更新电站绑定
     * @param roleId 角色ID
     * @param stationIdList 菜单ID列表
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void updateStation(Long roleId, List<Long> stationIdList)
            throws DatabaseProcessException;

    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void updateHasStation(Long roleId, List<Long> stationIdList)
            throws DatabaseProcessException;

    Role getParentRole(Long id);

    Iterable<User> findActiveUsersById(Long id);

    Boolean findExists(Role role1, Role role2);

    /************************/
    /**
     * 根据项目id或者单位id查询角色
     * @param firmId 单位ID
     * @param stationId 项目ID
     * @return
     */
    List<Role> findRolesByStationIdOrFirmId(Long stationId, Long firmId);

    /**
     * 根据项目id或者单位id查询角色(分页)
     * @param firmId 单位ID
     * @param stationId 项目ID
     * @param keywords 关键词
     * @param pageParam 分页
     * @return Page
     */
    Page<Role> findRolesByStationIdOrFirmIdForPage(Long stationId, Long firmId, String keywords, PageParam pageParam);

    /**
     * 角色绑定菜单列表
     * @param roleId    角色id
     * @param menuIds   菜单列表
     * @param systemMenuCategory
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    void roleBindMenus(Long roleId, String menuIds, String systemMenuCategory) throws ArgumentErrorException, ObjectNotFoundException;

    /**
     * 通过角色id 批量查询角色信息
     * @param roleIds
     * @return
     */
    Iterable<Role> findByRoleIds(List<Long> roleIds);

    /**
     * 通过用户id和电站id 查询角色信息
     * @param userId
     * @param stationId
     * @param firmId
     * @return
     */
    Iterable<Role> findByUserId(Long userId, Long stationId, Long firmId);

    /**
     * 通过用户id和电站id 查询角色信息
     * @param userId
     * @param stationId
     * @param firmId
     * @param roleType
     * @return
     */
    Iterable<Role> findByUserId(Long userId, Long stationId, Long firmId, String roleType);

    /**
     * 根据当前登录人以及选择的项目确定对应的角色以及当前项目的组织以及记录当前访问的项目
     * @param stationId
     * @param firmId
     * @return
     */
    ProejctRoleOrg getRoleByLoginUser(Long stationId, Long firmId) throws ArgumentErrorException;

    List<Role> findByEmployeeId(Long employeeId);
}
